package com.flkin.security;

import com.flkin.common.exception.BadRequestException;
import com.flkin.modules.system.domain.Authority;
import com.flkin.modules.system.domain.Role;
import com.flkin.modules.system.domain.User;
import com.flkin.modules.system.service.AuthorityService;
import com.flkin.modules.system.service.RoleService;
import com.flkin.modules.system.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.HashSet;
import java.util.Set;

/**
 * @author yanxiang.huang
 */
@Service("userDetailsService")
@Slf4j
public class IUserDetailsService implements UserDetailsService {

    @Resource
    private UserService userService;
    @Resource
    private RoleService roleService;
    @Resource
    private AuthorityService authorityService;

    @Override
    public IUserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        log.info("load user by username:{}", username);
        User user = userService.findByName(username);
        if (user == null) {
            throw new BadRequestException("user not found, please check your input");
        }
        Set<GrantedAuthority> authorities = new HashSet<>();
        Set<Role> roles = roleService.findByUserId(user.getId());
        for (Role role : roles) {
            String roleName = role.getName();
            authorities.add(new SimpleGrantedAuthority(roleName));
            Set<Authority> roleAuthorities = authorityService.findByRoleId(role.getId());
            for (Authority roleAuthority : roleAuthorities) {
                authorities.add(new SimpleGrantedAuthority(roleAuthority.getName()));
            }
        }
        return new IUserDetails(user, authorities);
    }

}
